package com.kifas.service.dataaccess;

import java.util.Date;
import java.util.List;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.kifas.entity.CustomerEntity;
import com.kifas.entity.PenjualanDetailEntity;
import com.kifas.entity.PenjualanEntity;
import com.kifas.entity.SalesEntity;

@Repository
public class PenjualanDao {

	@Autowired
	private SessionFactory sessionFactory;
	private final static String ALL_PENJUALAN = "from PenjualanEntity pe";
        private final static String ALL_PENJUALAN_IS_CLOSED = "from PenjualanEntity pe where pe.closed = :closed";
	private final static String ALL_PENJUALANDETAIL = "from PenjualanDetailEntity pd ";
	private final static String PENJUALAN_BY_ID = ALL_PENJUALAN
			+ " where pe.idPenjualan = :idPenjualan";
	private final static String PENJUALAN_BY_CUSTOMER = ALL_PENJUALAN
			+ " where pe.customer = :customer";
	private final static String PENJUALAN_BY_SALES = ALL_PENJUALAN
			+ " where pe.sales = :sales";
	private final static String PENJUALAN_BY_DATE_RANGE = ALL_PENJUALAN
			+ " where pe.tanggal >= :startDate and pe.tanggal <= :endDate) ";
	private final static String PENJUALAN_BY_DATE_RANGE_SENT_STATUS = ALL_PENJUALAN
			+ " where pe.kirim = :sentStatus and pe.tanggal >= :startDate and pe.tanggal <= :endDate) ";
	private final static String PENJUALAN_BY_TGL_JTH_TEMPO = ALL_PENJUALAN
			+ " where pe.tanggalJatuhTempo <= :startDate and pe.kirim = false ";
	private static final String PENJUALAN_UNSENT = ALL_PENJUALAN
			+ " where pe.kirim = false";
	private static final String PENJUALAN_BY_IDS = ALL_PENJUALAN
			+ " where pe.idPenjualan in :ids";
	private static final String PENJUALANDETAIL_BY_PARENT = ALL_PENJUALANDETAIL
			+ " where pd.penjualan = :parent";
	private static final String ALL_PENJUALAN_AND_DETAIL = ALL_PENJUALAN
			+ " left join fetch PenjualanDetailEntity pd";
	private static final String ALL_PENJUALAN_AND_DETAIL_RANGED_BY_DATE = ALL_PENJUALAN
			+ " left join fetch PenjualanDetailEntity pd"
			+ " where pe.tanggal between :startDate and :endDate";

	@SuppressWarnings("unchecked")
	public List<PenjualanEntity> getPenjualans() {
		return sessionFactory.getCurrentSession().createQuery(ALL_PENJUALAN)
				.list();
	}

        @SuppressWarnings("unchecked")
	public List<PenjualanEntity> getPenjualansIsClosed(boolean isClosed) {
		return sessionFactory.getCurrentSession().createQuery(ALL_PENJUALAN_IS_CLOSED)
                        .setParameter("closed", isClosed)
				.list();
	}

	@SuppressWarnings("unchecked")
	public List<PenjualanEntity> getPenjualanAndDetails() {
		return sessionFactory.getCurrentSession()
				.createQuery(ALL_PENJUALAN_AND_DETAIL).list();
	}

	@SuppressWarnings("unchecked")
	public List<PenjualanEntity> getPenjualanAndDetails(Date startDate,
			Date endDate) {
		return sessionFactory.getCurrentSession()
				.createQuery(ALL_PENJUALAN_AND_DETAIL_RANGED_BY_DATE)
				.setDate("startDate", startDate).setDate("endDate", endDate)
				.list();
	}

	public PenjualanEntity getPenjualanById(Long id) {
		return (PenjualanEntity) sessionFactory.getCurrentSession()
				.createQuery(PENJUALAN_BY_ID).setLong("idPenjualan", id)
				.uniqueResult();
	}

	@SuppressWarnings("unchecked")
	public List<PenjualanEntity> getPenjualans(List<Long> ids) {
		return sessionFactory.getCurrentSession().createQuery(PENJUALAN_BY_IDS)
				.setParameter("ids", ids).list();
	}

	@SuppressWarnings("unchecked")
	public List<PenjualanEntity> getPenjualans(CustomerEntity customerEntity) {
		return sessionFactory.getCurrentSession()
				.createQuery(PENJUALAN_BY_CUSTOMER)
				.setEntity("customer", customerEntity).list();
	}

	@SuppressWarnings("unchecked")
	public List<PenjualanEntity> getPenjualans(SalesEntity salesEntity) {
		return sessionFactory.getCurrentSession()
				.createQuery(PENJUALAN_BY_SALES)
				.setEntity("sales", salesEntity).list();
	}

	@SuppressWarnings("unchecked")
	public List<PenjualanEntity> getPenjualans(Date start, Date end) {
		return sessionFactory.getCurrentSession()
				.createQuery(PENJUALAN_BY_DATE_RANGE)
				.setDate("startDate", start).setDate("endDate", end).list();
	}

	@SuppressWarnings("unchecked")
	public List<PenjualanEntity> getPenjualans(Date start, Date end,
			boolean sentStatus) {
		return sessionFactory.getCurrentSession()
				.createQuery(PENJUALAN_BY_DATE_RANGE_SENT_STATUS)
				.setDate("startDate", start).setDate("endDate", end)
				.setParameter("sentStatus", sentStatus).list();
	}

	@SuppressWarnings("unchecked")
	public List<PenjualanEntity> getPenjualansJthTempo(Date start) {
		return sessionFactory.getCurrentSession()
				.createQuery(PENJUALAN_BY_TGL_JTH_TEMPO)
				.setDate("startDate", start).list();
	}

	public void insert(PenjualanEntity penjualan) throws Exception {
		sessionFactory.getCurrentSession().save(penjualan);
		for (PenjualanDetailEntity detail : penjualan.getPenjualanDetails()) {
			sessionFactory.getCurrentSession().save(detail);
		}
	}

	@SuppressWarnings("unchecked")
	public List<PenjualanEntity> getUnsentPenjualans() {
		return sessionFactory.getCurrentSession().createQuery(PENJUALAN_UNSENT)
				.list();
	}

	@SuppressWarnings("unchecked")
	public List<PenjualanDetailEntity> getPenjualanDetailEntities(
			PenjualanEntity penjualan) {
		return sessionFactory.getCurrentSession()
				.createQuery(PENJUALANDETAIL_BY_PARENT)
				.setEntity("parent", penjualan).list();
	}

	public void updatePengirimanFlag(Long idPenjualan) {
		PenjualanEntity penjualan = getPenjualanById(idPenjualan);
		penjualan.setKirim(true);
		sessionFactory.getCurrentSession().save(penjualan);
	}

	public void updateClosedFlag(Long idPenjualan) {
		PenjualanEntity penjualan = getPenjualanById(idPenjualan);
		penjualan.setClosed(true);
		sessionFactory.getCurrentSession().save(penjualan);
	}
}
